package com.s7.widget.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.s7.widget.utils.PxUtil;


/**
 * 自定义节点可拖动进度条
 */

public class NodeView extends View {


    private final int REFLASH_VIEW = 1;
    private final int SMOLL_FINISH = 2;

    String TAG = "NodeView";

    private Context context;

    private int mWidth;
    private int mHeight;

    private float lineWidth;
    private float lineY;

    private float realHeight;

    private int seekbarWidht;
    private int seekbarRadius;

    private Point newPoint;
    private Point realPoint;

    boolean isSelect = false;

    private int level = 6;
    private int levelWidth;
    private int[] levelXs;

    private Paint paintBg;
    private Paint paintSelBg;
    private Paint paintScale;
    private Paint paintSelScale;
    private Paint paintCycle;

    public NodeView(Context context) {
        super(context);
        init(context);
    }

    public NodeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public NodeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {
        this.context = context;

        lineWidth = PxUtil.dp2px(context, 3);

        realHeight = PxUtil.dp2px(context, 5);

        isSelect = false;

        realPoint = new Point();
        newPoint = new Point();

        paintCycle = new Paint();
        paintCycle.setAntiAlias(true);
        paintCycle.setColor(Color.parseColor("#20AEE4"));

        paintBg = new Paint();
        paintBg.setAntiAlias(true);
        paintBg.setStrokeWidth(lineWidth);
        paintBg.setColor(Color.parseColor("#D7D7D7"));

        paintSelBg = new Paint();
        paintSelBg.setAntiAlias(true);
        paintSelBg.setStrokeWidth(lineWidth);
        paintSelBg.setColor(Color.parseColor("#20AEE4"));

        paintScale = new Paint();
        paintScale.setAntiAlias(true);
        paintScale.setStrokeWidth(lineWidth / 2);
        paintScale.setColor(Color.parseColor("#D7D7D7"));

        paintSelScale = new Paint();
        paintSelScale.setAntiAlias(true);
        paintSelScale.setStrokeWidth(lineWidth / 2);
        paintSelScale.setColor(Color.parseColor("#20AEE4"));

        seekbarWidht = PxUtil.dp2px(context, 20);
        seekbarRadius = seekbarWidht / 2;
        realPoint.x = seekbarRadius;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();

        levelWidth = mWidth / (level - 1);

        lineY = mHeight / 2;

        realPoint.y = mHeight / 2;
        initLevelXs();
        setMeasuredDimension(mWidth, mHeight);
    }

    private void initLevelXs() {
        levelWidth = (mWidth - seekbarWidht) / (level - 1);
        levelXs = new int[level];
        for (int i = 0; i < 6; i++) {
            levelXs[i] = seekbarRadius + levelWidth * i;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawSeekBg(canvas);
        drawSeekScale(canvas);
        drawSeekBar(canvas);
        if (mListener != null) {
            mListener.onSmollChange((int) (float) realPoint.x / (float) mWidth * 100);
        }
    }

    private void drawSeekBg(Canvas canvas) {
        canvas.drawLine(realPoint.x, lineY, mWidth - seekbarRadius, lineY, paintBg);
        canvas.drawLine(seekbarRadius, lineY, realPoint.x, lineY, paintSelBg);
    }

    private void drawSeekScale(Canvas canvas) {
        for (int i = 0; i < level; i++) {
            int scaleSeat = levelWidth * i + seekbarRadius;
            if (scaleSeat > realPoint.x) {
                canvas.drawLine(scaleSeat, lineY - realHeight, scaleSeat, lineY + lineWidth / 3, paintScale);
            } else {
                canvas.drawLine(scaleSeat, lineY - realHeight, scaleSeat, lineY + lineWidth / 3, paintSelScale);
            }
        }
    }

    private void drawSeekBar(Canvas canvas) {
        canvas.drawCircle(realPoint.x, realPoint.y, seekbarRadius, paintCycle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int x = (int) event.getX();
        int y = (int) event.getY();

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (x < realPoint.x + seekbarRadius + 8 && x > realPoint.x - seekbarRadius - 8
                    && y < realPoint.y + seekbarRadius + 8 && y > realPoint.y - seekbarRadius - 8) {
                isSelect = true;
            } else {
                //do click
                moveX(x);
            }
        }

        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            if (isSelect) {
                moveX(x);
            }
        }

        if (event.getAction() == MotionEvent.ACTION_UP) {
            isSelect = false;
            new NodeView.MoveThread().start();
        }

        invalidate();
        return true;
    }

    int moveScale = 3;
    boolean isNeedMove = false;

    public class MoveThread extends Thread {
        @Override
        public void run() {
            isNeedMove = true;
            int targetX = levelXs[getLevel()];
            newPoint.x = targetX;
            newPoint.y = realPoint.y;
            while (!isSelect && isNeedMove) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int abs = newPoint.x > realPoint.x ? 1 : -1;
                if (Math.abs(realPoint.x - newPoint.x) < moveScale) {
                    realPoint.x = newPoint.x;
                    isNeedMove = false;
                } else {
                    realPoint.x += moveScale * abs;
                }
                reflashView.sendEmptyMessage(REFLASH_VIEW);
            }
            reflashView.sendEmptyMessage(SMOLL_FINISH);
        }
    }


    Handler reflashView = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == REFLASH_VIEW) {
                invalidate();
            }
            if (msg.what == SMOLL_FINISH) {
                if (mListener != null) {
                    mListener.onLevelChange(getLevel());
                }
            }
        }
    };

    private void moveX(int x) {
        if (x < seekbarRadius) {
            realPoint.x = seekbarRadius;
        } else if (x > mWidth - seekbarRadius) {
            realPoint.x = mWidth - seekbarRadius;
        } else {
            realPoint.x = x;
        }

    }

    public int getLevel() {
        int result = 0;

        int minD = Math.abs(realPoint.x - levelXs[0]); //最小距离
        for (int i = 1; i < level; i++) {
            if (Math.abs(realPoint.x - levelXs[i]) < minD) {
                minD = Math.abs(realPoint.x - levelXs[i]);
                result = i;
            }
        }
        return result;
    }

    public void setLevelNow(int levelNow) {
        if (isSelected()) {
            return;
        }
        try {
            isNeedMove = false;
            realPoint.x = levelXs[levelNow];
            postInvalidate();
        } catch (NullPointerException ex) {
            ex.printStackTrace();
        }
    }


    public interface OnLevelChangeListener {

        void onSmollChange(float percent);

        void onLevelChange(int level);
    }

    private OnLevelChangeListener mListener;
    public void setOnLevelChangeListener(OnLevelChangeListener mListener) {
        this.mListener = mListener;
    }
}
